package cn.feilue.app.service.core;

import cn.feilue.app.service.PersonnelService;
import cn.feilue.app.service.commone.*;
import cn.feilue.app.service.config.EmailConfig;
import cn.feilue.app.service.config.RedisUtilDes;
import cn.feilue.app.service.config.SMSConfig;
import cn.feilue.app.service.send.SendEmail;
import cn.feilue.app.service.send.SendSMS;
import cn.feilue.app.service.send.TengXunSendSms;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.xerces.internal.xs.ShortList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static cn.feilue.app.service.commone.Constants.*;

@Component
public class Core {
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private SendEmail sendEmail;
    @Autowired
    private TengXunSendSms tengXunSendSms;
    @Autowired
    private CoreDateImpl coreDate;
    @Autowired
    private SMSConfig smsConfig;
    @Autowired
    private RedisUtilDes redisUtil;
    @Autowired
    private EmailConfig emailConfig;

    private static Logger log =   LoggerFactory.getLogger(Core.class);

    public Core() {
    }

    public  void taskSMS() {
        boolean isSendSMS = redisUtil.get(IS_OPEN_SEND_SMS).equals("1");
        if(isSendSMS){
            this.task(SendOptEnum.SMS.getCode());
        }else{
            log.error("未开启短信发送");
        }

    }

    public  void taskEmail() {
        boolean isOpenEmail = redisUtil.get(IS_OPEN_SEND_EMAIL).equals("1");
        if(isOpenEmail){
            this.task(SendOptEnum.EMAIL.getCode());
        }else{
            log.error("未开启邮件发送");
        }

    }

    /**

     * @param opt 1:邮件；2:短信
     */
    public  void task(int opt) {
        CheckResult result = coreDate.check();

        System.out.println("result = " + result);
        List<String> personnelList = null;
        switch (opt) {
            case 1:
                //获取人员列表
                personnelList = personnelService.recipientList(SendOptEnum.EMAIL);
                sendEmail(result,personnelList);
                break;
            case 2:
                //获取人员列表
                personnelList = personnelService.recipientList(SendOptEnum.SMS);
                sendSMS(result,personnelList);
                break;
            default:
                log.info("未定义发送方式");
        }
    }

    /**
     * 添加 邮箱和手机号时  检查是否是十斋日 发送
     */
    public void specifiedSend(String personnel,SendOptEnum sendOpt){
        List<String> personnelList = new ArrayList<>();
        personnelList.add(personnel);
        CheckResult result = coreDate.check();
        if(SendOptEnum.EMAIL.equals(sendOpt)){
            sendEmail(result,personnelList);
        }else{
            sendSMS(result,personnelList);
        }
    }


    private  void sendEmail(CheckResult result,List<String> personnelList) {

        log.info("接收件人邮件列表:"+personnelList.toString());
        switch (result.getFlag()) {
            case 1:
                sendShiZaiEmail(result, personnelList);
                break;
            case 2:
                sendShengDanEmail(result, personnelList);
                break;
            case 3:
                sendShiZaiEmail(result, personnelList);
                sendShengDanEmail(result, personnelList);
                break;
        }

    }

    private  void sendSMS(CheckResult result,List<String> personnelList) {

        log.info("接收件人短信列表:"+personnelList.toString());
        switch (result.getFlag()) {
            case 1:
                sendShiZaiPhone(result, personnelList);
                break;
                /*case 2:
                sendShengDanPhone(result, personnelList);
                break;
                case 3:
                sendShiZaiPhone(result, personnelList);
                try {
                Thread.sleep(smsConfig.getResendSendTime());
                } catch (InterruptedException e) {
                throw new RuntimeException(e);
                }
                sendShengDanPhone(result, personnelList);
                break;*/
        }
    }

    private  void sendShiZaiPhone(CheckResult result, List<String> personnelList) {
        log.info("发送十斋日短信开始.... ");
                    /*String templateParam = SmsTemplateEnum.SHIZAIRI.getTemplateParam();
                    String labelParam = SmsTemplateEnum.SHIZAIRI.getLabelParam();
                    templateParam = templateParam.replace(labelParam,result.getDate());
                    sendSMS.send(personnelList, SmsTemplateEnum.SHIZAIRI,templateParam);*/
        tengXunSendSms.send(personnelList,SmsTemplateEnum.SHIZAIRI,"善男信女",result.getDate());
        log.info("发送十斋日短信结束.... ");
    }

    private  void sendShengDanPhone(CheckResult result, List<String> personnelList) {
        log.info("发送佛菩萨圣诞日短信开始.... ");
                        /*  String templateParam = SmsTemplateEnum.SHENDAN.getTemplateParam();
                        String labelParam = SmsTemplateEnum.SHENDAN.getLabelParam();
                        templateParam = templateParam.replace(labelParam,result.getDate());
                        sendSMS.send(personnelList, SmsTemplateEnum.SHENDAN,templateParam);*/
        log.info("发送佛菩萨圣诞日短信结束.... ");
    }

    private  void sendShiZaiEmail(CheckResult result, List<String> personnelList) {
        log.info("发送十斋日邮件开始.... ");
        sendEmail.sendToEmails(personnelList, "明天"+result.getDate()+"是十斋日", result.getShiZaiCents());
        log.info("发送十斋日邮件结束.... ");
    }

    private  void sendShengDanEmail(CheckResult result, List<String> personnelList) {
        log.info("发送菩萨圣诞日邮件开始.... ");
        sendEmail.sendToEmails(personnelList, result.getName(), result.getPusaChristmasCents());
        log.info("发送菩萨圣诞日邮件结束.... ");
    }

    private  void errorEmailRetrySend() {
        Map<Object, Object> hashEntries = redisUtil.getHashEntries(SEND_EMAIL_ERROR);
        if(hashEntries == null) return;
        redisUtil.delete(SEND_EMAIL_ERROR);

        log.info("邮件错队列："+ hashEntries.keySet().toString());

        //超过3次需要人工干预
        List<SendEmailError> errors = new ArrayList<>();
        Set<Object> keySet = hashEntries.keySet();
        keySet.forEach(entity -> {
            String value = hashEntries.get(entity).toString();
            SendEmailError error = JSON.parseObject(value, SendEmailError.class);
            error.setRetryNum(error.getRetryNum() == null ? 0 : error.getRetryNum());
            if (error.getRetryNum() >= RETRY_SEND_EMAIL_NUMBER) {
                errors.add(error);
                return;
            }
            try {
                sendEmail.sendToEmail(error.getToEmails(), error.getSubject(), error.getContent());
            } catch (Exception e) {
                log.error("邮件重试发送错误：" + e.getMessage());
                error.setErrorLog(e.getMessage());
                error.setRetryNum(error.getRetryNum() + 1);
                redisUtil.put(SEND_EMAIL_ERROR, error.getToEmails(), JSON.toJSON(error).toString());
            }
        });

        //超过重发次数 需要 人工处理
        if(errors.size() > 0){
            AtomicReference<String> cont = new AtomicReference<>("");
            errors.forEach(entity->{
                String s = cont.get() + JSON.toJSONString(entity).toString() +"@@";
                cont.set(s);
            });

            try {
                sendEmail.sendToEmail(emailConfig.getInitializer(),RETRY_SEND_EMAIL_TITLE,cont.get());
            } catch (Exception e) {
                log.error("人工处理邮件发送错误.."+cont.get());
            }

        }
    }


    public void start(){



        init();


        Runnable taskEmail = () -> {
            log.info("发送邮件定时器开始启动 = =====");
            this.taskEmail();
            log.info("发送邮件定时器启动成功 = =====");
        };

        Runnable taskBirthday = () -> {
            log.info("发送生日定时器开始启动 = =====");
            this.sendSmsShengri();
            log.info("发送生日定时器启动成功 = =====");
        };

        Runnable errorEmail = ()->{
            this.errorEmailRetrySend();
        };

        Runnable taskSMS = () -> {

            log.info("发送短信定时器开始启动 = =====");
            taskSMS();
            log.info("发送短信定时器启动成功 = =====");
        };

        /* Runnable resendSendSMS = () -> {

        log.info("重发短信定时器开始启动 = =====");
        try {
        sendSMS.timingResendSend();
        } catch (Exception e) {
        throw new RuntimeException(e);
        }
        log.info("重发短信定时器启动成功 = =====");
        };
        */
        log.info("发送服务启动开始......");
        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(3);
        executorService.scheduleAtFixedRate(taskEmail, 0, 1, TimeUnit.DAYS);
        executorService.scheduleAtFixedRate(taskSMS, 0, 1, TimeUnit.DAYS);
        executorService.scheduleAtFixedRate(taskBirthday, 0, 1, TimeUnit.DAYS);
        //        executorService.scheduleAtFixedRate(resendSendSMS,0,1,TimeUnit.MINUTES);
        log.info("发送服务启动成功......");

        //        this.taskEmail();

        //错误邮件定时检测
        //        executorService.schedule(errorEmail,5, TimeUnit.MINUTES);
    }

    /**
     * 初始化邮件和电话相关
     */
    private void init(){

        setRedis(SendOptEnum.EMAIL);
        setRedis(SendOptEnum.SMS);
        log.info("初始化邮件列表:"+PublicSendValue.recipientMap.get(SendOptEnum.EMAIL));
        log.info("初始化sms列表:"+PublicSendValue.recipientMap.get(SendOptEnum.SMS));
    }

    private void setRedis(SendOptEnum sendOptEnum){
        String send = SendOptEnum.EMAIL.equals(sendOptEnum) ? SEND_EMAILS :SEND_SMS;
        //初始化邮件列表
        Map<Object, Object> entries = redisUtil.getHashEntries(send);
        Set<Object> keySet = entries.keySet();
        List<String> emailList = new ArrayList<>();
        keySet.forEach(key->{

            String value = entries.get(key).toString();
            PublicSendValue.phoneMap.put(key.toString(),value);
            emailList.add(key.toString());


        });
        PublicSendValue.recipientMap.put(sendOptEnum,emailList);
    }

    private void setMap(Map<Object,Object> maps){
        Set<Object> objects = maps.keySet();
        objects.forEach(entity->{
            String key = maps.get(entity).toString();
            redisUtil.put("email2",key,entity.toString());
        });

    }

    public void sendSmsShengri(){
        Map<String,String> map = new HashMap<>();
//        map.put("十一月初一","测试");
        CheckBirthdayResult result = coreDate.checkBirthday(map);
        if(WhetherEnum.YES.equals(result.getFlag())){
            log.info("生日提醒："+result.getBirthday().toString());
            List<CheckBirthdayResult.Birthday> birthday = result.getBirthday();
            birthday.forEach(entity->{
                SendMessage send = tengXunSendSms.send(smsConfig.getInitializer(), SmsTemplateEnum.SHIRI, entity.getDate(), entity.getName());
                log.info("生日提醒："+entity.toString()+",发送结果："+send.getError());
            });
        }
    }

}
